//
// Created by benxb on 2021/11/28.
//

#ifndef BENXDB_DATABASE_H
#define BENXDB_DATABASE_H

#include <unordered_map>
#include "mem/mem_data_table.h"
#include "catelog/query.h"
#include "mem/data_table_manager.h"
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include "catelog/point_type.h"
#include "catelog/point_cloud.h"

namespace benxdb {

class Database {
public:
    Database();
    ~Database();

    /**
     * Create Dataset with name and its type
     * @param dataset_name name of dataset
     * @param dataset_type type
     * @return
     */
    bool CreateDataset(const std::string& dataset_name, DatasetType dataset_type);

    /**
     * Create new table
     * @param table table meta
     * @return true if success
     */
    bool CreateTable(const std::shared_ptr<Table>& table);

    bool AppendPointCloud(const std::string& table_name, const pcl::PointCloud<pcl::PointXYZ>&);

    bool AppendPointCloud(const std::string& table_name, PointCloud<PointXYZI>& point_cloud);

    bool AppendPointCloud(const std::string& table_name, PointCloud<PointSTXYZ>& point_cloud);

    bool AppendPointCloud(const std::string& table_name, PointCloud<PointSTXYZC>& point_cloud);

    bool DeleteTuple(std::string table_name, Tuple tuple);

    bool Query(QueryPhrase query, std::vector<Tuple>& res);

    /**
     * query point cloud
     * @param query query phrase
     * @param res result point cloud
     * @return true if query successful
     */
    bool QueryPointCloud(PointCloudQuery& query, PointCloud<PointXYZ>& res);

    void AllDatasets(std::vector<std::string>& dataset_names);

private:
    std::unordered_map<std::string, std::shared_ptr<Table>> tables_;
    std::unordered_map<std::string, DataTableManager*> table_managers_;

    static bool AppendPoint(DataTableManager* table_manager, pcl::PointXYZ point);
    static bool AppendPoint(DataTableManager* table_manager, PointXYZI point);
    static void AppendManyPoints(DataTableManager* table_manager, const std::shared_ptr<std::vector<PointXYZI>>& points);

    static void FillColumnsByType(DatasetType type, std::vector<benxdb::Column>& columns);

    // load table from disk file
    bool LoadTable(const std::string &basicString);

    /**
     * Check whether table with table_name has already exist
     * @param table_name
     * @return
     */
    static bool TableExist(const std::string &table_name);
};

}


#endif //BENXDB_DATABASE_H
